package main

import (
	"fmt"
	"math"
	"reflect"
	"runtime"
)

func eval(a, b int, op string) int {
	switch op {
	case "+":
		return a + b
	case "-":
		return a - b
	case "*":
		return a * b
	case "/":
		if b == 0 {
			panic("除数不能为0")
		}
		// 可以丢弃第2个返回值
		quotient, _ := div(a, b)
		return quotient
	default:
		panic("不支持的运算符：" + op)
	}
}

/*
除法函数，同时返回商和余数
*/
func div(a, b int) (quotient, remainder int) {
	if b == 0 {
		panic("除数不能为0")
	}
	return a / b, a % b
}

/*
panic会引起程序中断
改进eval()方法，使用返回error的方式
*/
func eval2(a, b int, op string) (int, error) {
	switch op {
	case "+":
		return a + b, nil
	case "-":
		return a - b, nil
	case "*":
		return a * b, nil
	case "/":
		if b == 0 {
			return 0, fmt.Errorf("除数不能为0")
		}
		// 可以丢弃第2个返回值
		quotient, _ := div(a, b)
		return quotient, nil
	default:
		return 0, fmt.Errorf("不支持的运算符：%s", op)
	}
}

/*
改进eval2()方法，使用函数式编程简化代码
*/
func eval3(a, b int, op func(int, int) int) int {
	p := reflect.ValueOf(op).Pointer()
	pName := runtime.FuncForPC(p).Name()
	fmt.Printf("Calling function %v with args (%d, %d)\n", pName, a, b)
	return op(a, b)
}

/*
整数幂函数运算
*/
func pow(a, b int) int {
	return int(math.Pow(float64(a), float64(b)))
}

func sum(numbers ...int) int {
	sum := 0
	for _, v := range numbers {
		sum += v
	}

	return sum
}

func main() {
	fmt.Println(
		eval(6, 2, "+"),
		eval(6, 2, "-"),
		eval(6, 2, "*"),
		eval(6, 2, "/"),
		//eval(6, 2, "?"),
		//eval(6, 0, "/"),
	)
	a := 7
	b := 2
	quotient, remainder := div(a, b)
	fmt.Printf("%d / %d = %d ... %d\n", a, b, quotient, remainder)

	if result, err := eval2(6, 2, "?"); err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(result)
	}
	if result, err := eval2(6, 2, "*"); err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(result)
	}
	if result, err := eval2(6, 0, "/"); err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(result)
	}

	fmt.Println(eval3(6, 2, pow))
	fmt.Println(eval3(6, 2, func(a int, b int) int {
		return int(math.Pow(float64(a), float64(b)))
	}))

	fmt.Println(sum(1, 2, 3, 4, 5))
}
